package traceClient;

import java.awt.Point;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * @author jc
 * Classe permettant de lire un fichier xml de trace émit par le serveur et de
 * produire un fichier SVG à partir de celui-ci
 */
public class TraceClient {
	private static int width,height,marge,pasTps,hMax,lastTime;
	private static String angle;
	private static String svg; 
	private static Vector vFlechesHorizontales;
	private static Vector vFlechesVerticales;
	
	/**
	 * Parse le fichier XML et fait appel a la methode message chaque fois qu'un message est lu
	 * Message se charge alors de creer les fleches correspondantes dans le fichier SVG
	 *
	 */
	private static void parseXML(){
		try{
			// creation d'une fabrique de documents
			DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();

			// creation d'un constructeur de documents
			DocumentBuilder constructeur = fabrique.newDocumentBuilder();

			// lecture du contenu du fichier xml de trace avec DOM
			File xml = new File("trace.xml");
			Document document = constructeur.parse(xml);

			// recuperation de la racine du document xml
			Element racine = document.getDocumentElement();

			NodeList nodeListe = racine.getElementsByTagName("EVENEMENT");

			for (int i=0; i<nodeListe.getLength(); i++){
				Element elt = (Element) nodeListe.item(i);
				message(elt);
			}

		}catch(ParserConfigurationException pce){
			System.out.println("Erreur de configuration du parseur DOM");
			System.out.println("lors de l'appel a fabrique.newDocumentBuilder();");
		}catch(SAXException se){
			System.out.println("Erreur lors du parsing du document");
			System.out.println("lors de l'appel a construteur.parse(xml)");
		}catch(IOException ioe){
			System.out.println("Erreur d'entree/sortie");
			System.out.println("lors de l'appel a construteur.parse(xml)");
		}
	}

	/**
	 * Lis les proprietes de l'evenement et trace la/les fleche(s) correspondante(s)
	 * 
	 * @param parametres La liste d'enfant de l'evenements qui contient ses proprietes
	 */
	private static void message(Element elt){
		String type = ""; String time = "";
		String st = "";
		NodeList enfants = elt.getChildNodes();

		System.out.println("\nNombre d'enfants : " + enfants.getLength());

		for (int i=0; i<enfants.getLength();i++){
			Node enfant = enfants.item(i);

			if (!enfant.getNodeName().equals("text"))
			{
				if (enfant.getNodeName().equals("TYPE"))
				{
					type = enfant.getTextContent();
					System.out.println(type + " i vaut: " + i);
				} else if (enfant.getNodeName().equals("TIME")){
					time = enfant.getTextContent();
					System.out.println(time + " i vaut: " +i);
				} else if (enfant.getNodeName().equals("IP")){

				}


			}


		}
		
		
		st = time.substring(10, 13);
		int t = Integer.parseInt(st);

		if (type.equals("DEMARRAGE_SERVEUR"))
		{
			// trace les axes de temps
			Point deb = new Point(marge,hMax);
			Point fin = new Point(width-marge,hMax);
			svg += traceFlecheHorizontale(deb,fin);
			deb = new Point(marge,height-marge);
			fin = new Point(width-marge,height-marge);
			svg += traceFlecheHorizontale(deb,fin);
			type = ""; time = "";
			lastTime = t;
		} 
		else if (type.equals("CONNEXION_CLIENT"))
		{
			if (t > lastTime) lastTime = t;
						
			// trace la connexion du client vers le serveur
			Point deb = new Point(lastTime,height-marge);
			Point fin = new Point(lastTime,hMax);
			svg += traceFlecheVerticale(deb,fin,"blue");

			lastTime += pasTps;
			// trace l'envoie du scenario du serveur vers le client
			deb = new Point(lastTime,hMax);
			fin = new Point(lastTime,height-marge);
			svg += traceFlecheVerticale(deb,fin,"blue");
			type = ""; time = "";
			lastTime += pasTps;
		}
		else if (type.equals("CONNEXION_CLIENT_VEILLE"))
		{
			if (t > lastTime) lastTime = t;
						
			// trace la connexion du client vers le serveur
			Point deb = new Point(lastTime,height-marge);
			Point fin = new Point(lastTime,hMax);
			svg += traceFlecheVerticale(deb,fin,"black");

			lastTime += pasTps;
			// trace l'envoie du scenario du serveur vers le client
			deb = new Point(lastTime,hMax);
			fin = new Point(lastTime,height-marge);
			svg += traceFlecheVerticale(deb,fin,"black");
			type = ""; time = "";
			lastTime += pasTps;
		}
		else if (type.equals("RECEPTION_RESULTAT"))
		{
			if (t >= lastTime) lastTime = t;
			
			Point deb = new Point(lastTime+pasTps,height-marge);
			Point fin = new Point(lastTime+pasTps,hMax);
			svg += traceFlecheVerticale(deb,fin,"green");
			type = ""; time = "";
			lastTime += 2*pasTps;
		}
		else if (type.equals("DECONNEXION_CLIENT"))
		{
			if (t >= lastTime) lastTime = t;

			Point deb = new Point(lastTime,height-marge);
			Point fin = new Point(lastTime,hMax);
			svg += traceFlecheVerticale(deb,fin,"red");
			type = ""; time = "";			
			lastTime += pasTps;
		}
		else if (type.equals("DECONNEXION_CLIENT_VEILLE"))
		{
			System.out.println("Dans deconnexion veille");
			System.out.print("t:"+t+" lastTime:"+lastTime);
			if (t >= lastTime) lastTime = t;

			Point deb = new Point(lastTime,height-marge);
			Point fin = new Point(lastTime,hMax);
			svg += traceFlecheVerticale(deb,fin,"red");
			type = ""; time = "";
			lastTime += pasTps;
			
		}
	}	

	/**
	 * Initialise le fichier SVG et commence les definitions d'objet
	 * en commencant par le rectange banc de fond
	 * 
	 * @param width : largeur du fichier svg de sortie
	 * @param height : hauteur du fichier svg de sortie
	 */
	private static void debutSVG(){
		// ecris le debut du fichier svg, commence les definition d'objets avec le rectange blanc
		svg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
		svg += "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
		svg += "<svg baseProfile=\"full\" x=\"0\" y=\"0\" width=\""+width+"\" height=\""+height+"\"\n";
		svg += "     xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"\n";
		svg += "     xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
		//svg += "<svg baseProfile=\"full\" x=\"0\" y=\"0\" width=\""+width+"\" height=\""+height+"\">\n";
		svg += "<title>Trace</title>\n";
		svg += "<defs>\n";
		svg += "<g><rect width=\""+width+"\" height=\""+height+"\" x=\"0\" y=\"0\" fill=\"white\" id=\"rectB\" /></g>\n";
		
	
		// trace une fleche horizontale pour l'apprentissage de svg --> disparaitra
		Point deb = new Point(marge, height-marge);
		Point fin = new Point(width-marge, height-marge);
		//svg += traceFlecheHorizontale(deb, fin);	
	}

	/**
	 * Definit une fleche horizontale
	 * Rempli un vecteur de proprietes pour ensuite pouvoir faire la rotation voulue
	 * 
	 * @param deb Point de debut de la fleche
	 * @param fin Point de fin de la fleche
	 * @return String contenant ce qu'il faut ecrire dans le fichier SVG pour definir la fleche
	 */
	private static String traceFlecheHorizontale(Point deb, Point fin){
		String s = "";
		int dFL = 10;
		int dFl = 5;
		String nomFleche = "flecheH"+vFlechesHorizontales.size();
		s += "<g id=\""+nomFleche+"\" style=\"stroke:black; fill:none; shape-rendering:crispEdges\" >\n";
		s += "<line x1=\""+deb.x+"\" y1=\""+deb.y+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
		s += "<line x1=\""+(fin.x-dFL)+"\" y1=\""+(fin.y-dFl)+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
		s += "<line x1=\""+(fin.x-dFL)+"\" y1=\""+(fin.y+dFl)+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
		s += "</g>\n";
		
		
		Vector vProps = new Vector(1);
		vProps.add("#"+nomFleche);
		vProps.add(angle);
		vProps.add(deb);
		vProps.add(fin);
		
		vFlechesHorizontales.add(vProps);
		
		return s;
	}

	/**
	 * Fait tourner la fleche a partir de ses proprietes
	 * 
	 * @return String contenant le <use transform="rotate"> SVG pour tracer la fleche
	 */
	private static String FlechesHorizontales(){
		String s = "";
		Vector vProps;
		Point deb;
		String ang;
		for(int i = 0; i < vFlechesHorizontales.size(); i++){
			vProps = (Vector) vFlechesHorizontales.get(i);
			ang = "0"; //(String) vProps.get(1);
			deb = (Point) vProps.get(2);
			s += "<use transform=\"rotate("+ang+","+(deb.x)+","+(deb.y)+")\" ";
			s += "x=\""+0+"\" y=\""+0+"\" xlink:href=\"";
			s += vProps.get(0)+"\"/>\n";
		}
		return s;
	}

	/**
	 * Definit une fleche verticale
	 * Rempli un vecteur de proprietes pour ensuite pouvoir faire la rotation voulue
	 * 
	 * @param deb Point de debut de la fleche
	 * @param fin Point de fin de la fleche
	 * @return String contenant ce qu'il faut ecrire dans le fichier SVG pour definir la fleche
	 */
	private static String traceFlecheVerticale(Point deb,Point fin,String color){
		System.out.println("Entre dans traceFlecheVerticale");
		String s = "";
		int dFL = 10;
		int dFl = 5;
		String nomFleche = "flecheV"+vFlechesVerticales.size();
		Vector vProps = new Vector(1);
		
		// si du bas vers le haut
		if (deb.y > fin.y){
			s += "<g id=\""+nomFleche+"\" style=\"stroke:"+color+"; fill:none; shape-rendering:crispEdges\" >\n";
			s += "<line x1=\""+deb.x+"\" y1=\""+deb.y+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
			s += "<line x1=\""+(fin.x-dFl)+"\" y1=\""+(fin.y+dFL)+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
			s += "<line x1=\""+(fin.x+dFl)+"\" y1=\""+(fin.y+dFL)+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
			vProps.add("#"+nomFleche);
			vProps.add(angle);
			
			//sinon, du haut vers le bas
		}else{
			s += "<g id=\""+nomFleche+"\" style=\"stroke:"+color+"; fill:none; shape-rendering:crispEdges\" >\n";			
			s += "<line x1=\""+deb.x+"\" y1=\""+deb.y+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
			s += "<line x1=\""+(fin.x-dFl)+"\" y1=\""+(fin.y-dFL)+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
			s += "<line x1=\""+(fin.x+dFl)+"\" y1=\""+(fin.y-dFL)+"\" x2=\""+fin.x+"\" y2=\""+fin.y+"\" />\n";
			vProps.add("#"+nomFleche);
			vProps.add("-"+angle);
		}
		s += "</g>\n";
		
		vProps.add(deb);
		vProps.add(fin);
		
		vFlechesVerticales.add(vProps);
		
		return s;
	}

	
	private static String rotateFlechesVerticales(){
		String s = "";
		Vector vProps;
		Point deb;
		String ang;
		for(int i = 0; i < vFlechesVerticales.size(); i++){
			vProps = (Vector) vFlechesVerticales.get(i);
			ang = (String) vProps.get(1);
			deb = (Point) vProps.get(2);
			s += "<use transform=\"rotate("+ang+","+(deb.x)+","+(deb.y)+")\" ";
			s += "x=\""+0+"\" y=\""+0+"\" xlink:href=\"";
			s += vProps.get(0)+"\"/>\n";
		}
		return s;
	}
	
	
	
	/**
	 * Fin de definition d'objets et debut des uses
	 * Commence par le rectangle blanc, puis le texte du graphique SVG 
	 */
	private static void finDefsDebutUse(){
		svg += "</defs>\n";
		svg += "<use x=\"0\" y=\"0\" xlink:href=\"#rectB\" />\n";
		svg += "<g style=\"text-rendering:optimizeLegibility;shape-rendering:crispEdges\">\n";
		svg += "<text x=\""+(width/2)+"\" y=\""+20+"\" text-anchor=\"middle\" style=\"font-size:14\">";
		svg += "Trace de l'optimisation des plans de Vol</text>\n";
		
		svg += "<text x=\""+marge+"\" y=\""+(height)+"\" text-anchor=\"left\" style=\"font-size:10\">";
		svg += "Démarrage</text>\n";
		
		svg += "<text x=\""+lastTime+"\" y=\""+(height)+"\" text-anchor=\"left\" style=\"font-size:10\">";
		svg += "Arrêt</text>\n";
		
		svg += "</g>\n";
	}
	
	/**
	 * Ecrit la balise fermante svg et ecrit le fichier SVG de sortie
	 *
	 */
	private static void finSVG(){
		svg += "</svg>\n";
		File file = new File("out.svg");
		FileWriter fw;
		try {
			fw = new FileWriter(file);
			fw.write(svg);
			fw.close();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("Debut du client de trace XML");
		width = 400; height = 200; marge = 15; angle = "4";
		pasTps = 10; hMax = 40; 
		
		vFlechesHorizontales = new Vector();
		vFlechesVerticales = new Vector();
		debutSVG();
		parseXML();
		
		/*
		Point deb = new Point(10,200);
		Point fin = new Point(10,100);
		svg += traceFlecheVerticale(deb,fin);
		
		Point deb1 = new Point(20,100);
		Point fin1 = new Point(20,200);
		svg += traceFlecheVerticale(deb1,fin1);
		*/
		
		finDefsDebutUse();
		svg += FlechesHorizontales();
		svg += rotateFlechesVerticales();
		finSVG();
		System.out.println("Fin du client de trace XML");
	}

}
